#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QDebug>
#include <QTcpServer>
#include <QTcpSocket>
//#include <QNetworkRequest>
//#include <QNetworkAccessManager>
//#include <QNetworkInterface>
#include <QSettings>
#include <QMessageBox>
#include <QSqlRecord>
#include <QAbstractSocket>

#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QNetworkInterface>
#include <QNetworkRequest>


const int MAX_CONNECT_COUNT = 10;

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    //ui->pbSend->setVisible(false);

    //db_o = QSqlDatabase::addDatabase("QOCI","db_o");
    db_m = QSqlDatabase::addDatabase("QMYSQL","db_m");

    /*
    host = setIni.value("database/o_hostname").toString();
    port = setIni.value("database/o_port").toString();
    dbnm = setIni.value("database/o_databasename").toString();
    usr = setIni.value("database/o_username").toString();
    pswd = setIni.value("database/o_password").toString();
    db_o.setPort(port.toInt());
    db_o.setHostName(host);
    db_o.setPassword(pswd);
    db_o.setUserName(usr);
    db_o.setDatabaseName(dbnm);

    if(!db_o.open()){
        QString tmp = "Can not open database ！ \nPort: "+port;
        tmp = tmp + "\nHost: "+host;
        tmp = tmp + "\nDBName: "+dbnm;

        QMessageBox::information(NULL,"注意",tmp);
    }

    */

    tcpServer = new QTcpServer(this);

//    if(!get_db_connect())
//    {
//        QMessageBox::information(this, "Note", "Database connect is failed!");
//    }

    for(int n = 0; n< MAX_CONNECT_COUNT; n++)
    {
        tcpSocket[n] = new QTcpSocket(this);
        //tqrmt = new QSqlQuery(db_m);
        //qro[n] = new QSqlQuery(db_o);
        //qrot[n] = new QSqlQuery(db_o);
        qrm[n] = new QSqlQuery(db_m);
        qrmt[n] = new QSqlQuery(db_m);
    }

    //获取本机工作IP
    QString iptmp ;
    QStringList ips;
    QList<QHostAddress> list = QNetworkInterface::allAddresses();
    foreach (QHostAddress address, list){
        if(address.protocol() == QAbstractSocket::IPv4Protocol){ //IPv4地址
            ips <<address.toString();
        }
    }

    iptmp = ips[0];
    ui->leIP->setText(iptmp);
    statusBar()->showMessage("Stoped.");
    tm = new  QTimer(this);
    connect(tm, SIGNAL(timeout()), this, SLOT(onTimeOut()));
    receiveData = false;

    qDebug() << "system started...";
}

bool MainWindow::get_db_connect()
{
    QSettings setIni("clin.ini", QSettings::IniFormat);
    QString host,port,dbnm, usr, pswd;

    host = setIni.value("database/m_hostname").toString();
    port = setIni.value("database/m_port").toString();
    dbnm = setIni.value("database/m_databasename").toString();
    usr = setIni.value("database/m_username").toString();
    pswd = setIni.value("database/m_password").toString();

    db_m.setPort(port.toInt());
    db_m.setHostName(host);
    db_m.setPassword(pswd);
    db_m.setUserName(usr);
    db_m.setDatabaseName(dbnm);
    if(!db_m.open()){
        return false;
    }

    QString str_display = "Database connected at " + QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
    ui->textEdit->append("\n");
    ui->textEdit->append(str_display);

    return true;
}
MainWindow::~MainWindow()
{

    for(int n = 0; n< MAX_CONNECT_COUNT; n++)
    {
        delete tcpSocket[n];
        //delete qro[n];
        //delete qrot[n];
        delete qrm[n];
        delete qrmt[n];
    }

    delete tcpServer;

    delete ui;

}

void MainWindow::on_pbSend_clicked()
{
    tcpSocket[9]->abort();
    tcpSocket[9]->disconnect();

    QString adr = ui->leIP->text() ;//+ ":" + ui->lePort->text(); //"http://" +
    tcpSocket[9]->connectToHost(adr, ui->lePort->text().toUInt() ) ;

    //if (tcpSocket[9]->waitForConnected(10000)) {
//QMessageBox::information(this, "Note", "连接 ！ ");
    //}
    //else
    //{
    //    QMessageBox::information(this, "Note", "连接超时 ！ ");
    //    return ;
    //}

    connect(tcpSocket[9], &QTcpSocket::connected,
            [=]()
    {
        qDebug()<<"tcpSocket[9] connected ! ";
        QByteArray data = ui->le_send->text().toUtf8();
        qDebug()<<"data to send : "<<data;
        tcpSocket[9]->write(data, data.length());

}    );



    // 读取数据
    connect(tcpSocket[9], &QTcpSocket::readyRead, [=]() {
        QByteArray receivedData = tcpSocket[9]->readAll();
        ui->textEdit->append("\n");
        ui->textEdit->append(QString(receivedData));
        //qDebug() << "Received data:" << receivedData;
    });

    // 处理错误
    //connect(tcpSocket[9], QOverload<QAbstractSocket::SocketError>::of(&QAbstractSocket::errorOccurred), [=](QAbstractSocket::SocketError socketError) {
    //    qDebug() << "Error occurred:" << socketError;
    //});
    // 处理连接断开
    connect(tcpSocket[9], &QTcpSocket::disconnected, [=]() {
        ui->textEdit->append("\n");
        ui->textEdit->append("Disconnected!");
        qDebug() << "Disconnected!";
    });


    /*
    connect(tcpSocket[9], &QTcpSocket::connected,
            [=]()
    {

        QJsonParseError json_error;
        QJsonDocument jsdc = QJsonDocument::fromJson(.toUtf8().data(), &json_error);
        if(json_error.error != 0 )
        {
            QMessageBox::information(this, "Note", "入参Json解析错误 " + json_error.errorString());
            return ;
        }

        QString info;
        QJsonObject retValue;


        QString str = "socket [%1] 服务端断开连接......%2";
        str = str.arg(QString::number(i_sock_idle_index))
                .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"));
        ui->textEdit->append("\n");
        ui->textEdit->append(str);

    }
    );

    */

    /*


    */

}

void MainWindow::on_pbStop_clicked()
{
    tm->stop();
    receiveData = false;
    statusBar()->showMessage("Stoped.");
    qDebug() << "receive stoped.";

    for(int i = 0 ; i< MAX_CONNECT_COUNT; i ++)
    {
        //if(tcpSocket[i] == NULL)
        //{
        //    continue;
        //}
        tcpSocket[i]->disconnectFromHost();
        tcpSocket[i]->close();
        //tcpSocket[i] = NULL;
    }

}

void MainWindow::on_pbReceive_clicked()
{

    tcpServer->listen(QHostAddress::Any, ui->lePort->text().toInt()); //监听端口

    connect(tcpServer, &QTcpServer::newConnection,
            [=]()
    {
        int i_sock_idle_index = 0;

        for(int i = 0; i< MAX_CONNECT_COUNT; i++)
        {
            if(tcpSocket[i]->state() == QAbstractSocket::UnconnectedState)
            {
                i_sock_idle_index = i;
                break;
            }
        }

        if(i_sock_idle_index >= MAX_CONNECT_COUNT)
        {
            ui->textEdit->append("无空闲 socket !");
            return;
        }


        QString str_display;

        //取出建立好链接的套接字
        tcpSocket[i_sock_idle_index] = tcpServer->nextPendingConnection();
        if (NULL == tcpSocket[i_sock_idle_index])
        {
            //strDisplay = QString(u8"客户端连接失败%3").arg(getCurrentTime());
            str_display = "客户端连接失败" + QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
            ui->textEdit->append("\n");
            ui->textEdit->append(str_display);
            return;
        }

        //获取对方的IP和端口
        QString strIP = tcpSocket[i_sock_idle_index]->peerAddress().toString();
        quint16 nPort = tcpSocket[i_sock_idle_index]->peerPort();

        str_display = "socket [%4] 连接成功，对方地址：[%1:%2]:%3";
        str_display = str_display.arg(strIP)
                .arg(QString::number(nPort))
                .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"))
                .arg(QString::number(i_sock_idle_index));

        ui->textEdit->append("\n");
        ui->textEdit->append(str_display);

        //建立套接字与读取的signal/slot
        connect(tcpSocket[i_sock_idle_index], &QTcpSocket::readyRead,
                [=]()
        {
            //从通信套接字中取出内容
            QByteArray array = tcpSocket[i_sock_idle_index]->readAll();

            qDebug() <<"套接字中取出内容:" << array;

            QString str = "socket [%1] receive data : %2 %3";
            str = str.arg(QString::number(i_sock_idle_index))
                    .arg(QString(array))
                    .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"));

            ui->textEdit->append("\n");
            ui->textEdit->append(str);

            QString ss= QVariant(array).toString();
            int pos = ss.indexOf("{");

            if(pos<0){
                //qDebug() << "not is a valid json.";
                qDebug() << "not is a valid json.";
                qDebug() << ss;

                ui->textEdit->append("\n");
                ui->textEdit->append(ss);
                return;
            }

            ss = ss.mid(pos);

            QJsonParseError json_error;

            QJsonDocument jsdc = QJsonDocument::fromJson(ss.toUtf8(), &json_error);


            if(json_error.error != 0 ){
                ui->textEdit->append("\n");
                ui->textEdit->append(json_error.errorString());
                qDebug()<<"接收信息解析错误 " << json_error.errorString();
                return;
            }


            QJsonObject ob = jsdc.object();
            qDebug()<<"received jsonObject : "<<ob;

            manipulate_query(ob, i_sock_idle_index);

        }
        );

        connect(tcpSocket[i_sock_idle_index], &QTcpSocket::disconnected,
                [=]()
        {
            QString str = "socket [%1] 服务端断开连接......%2";
            str = str.arg(QString::number(i_sock_idle_index))
                    .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"));
            ui->textEdit->append("\n");
            ui->textEdit->append(str);

        }
        );


    }
    );


    tm->start(500);
    receiveData = true;
    qDebug() << "receive started.";

}

void MainWindow::onTimeOut()
{
    if(statusBar()->currentMessage().isEmpty()){
        statusBar()->showMessage("Ready to receive data...");
    }else{
        statusBar()->clearMessage();
    }
    qApp->processEvents();  //刷新显示
}

bool MainWindow::manipulate_query(QJsonObject remote_qr, int channel)
{

    QString str_pageNum = remote_qr.value("pageNum").toString();    //页数
    QString str_pageSize = remote_qr.value("pageSize").toString();    //每页记录
    QString str_method = remote_qr.value("method").toString();    //接口编号
    QString str_orgCode = remote_qr.value("orgCode").toString();    //调用方机构编码
    QJsonObject jsob_qr = remote_qr.value("data").toObject();    //入参

    if(str_method == "ZHYY610")
    {

    }
    else if(str_method == "ZHYY610")
    {

    }
    else if(str_method == "ZHYY620")
    {

    }
    else if(str_method == "ZHYY630")
    {

    }
    else if(str_method == "ZHYY631")
    {

    }
    else if(str_method == "ZHYY640")
    {

    }
    else if(str_method == "ZHYY641")
    {

    }
    else if(str_method == "ZHYY642")
    {

    }
    else if(str_method == "ZHYY650")
    {

    }
    else if(str_method == "ZHYY651")
    {

    }
    else if(str_method == "ZHYY660")
    {

        QString str_id_no = jsob_qr.value("idCard").toString();

        QJsonArray ret = query_ZHYY660(str_id_no, channel);

        send_message(ret, channel);
    }

    return true;
}

bool MainWindow::send_message(QJsonArray jsar_msg, int channel)
{
    QJsonObject jsob_all;

    //    100：成功
    //    101-199：错误码段"

    jsob_all.insert("statusCode", "100"); /**接口响应编码*/
    jsob_all.insert("statusMessage", "成功");/**接口响应消息*/
    //jsob_all.insert("totalRecord", 150, /**总记录数 非分页不传*/
    jsob_all.insert("data", jsar_msg); /**具体接口出参数据*/

    QJsonDocument doc;
    doc.setObject(jsob_all);

    qDebug()<<"return from server : "<<jsob_all;

    QString header = "HTTP/1.1 200 OK\r\n\r\n";
    QByteArray bt = doc.toJson(QJsonDocument::Compact);

    int size = header.length() + bt.length()  ;

    QString http = header + bt;

    tcpSocket[channel]->write(http.toUtf8(), size); //发送

    //tcpSocket[channel]->waitForBytesWritten(size);//可省略

    tcpSocket[channel]->close();

    ui->textEdit->append("\n");
    ui->textEdit->append(http);

    return true;
}

QJsonArray MainWindow::query_ZHYY660(QString str_idenno, int channel)
{

    QJsonArray jsar_ret;
    QJsonObject jsob_tmp;
    QJsonObject jsob_state;

    //预置非复诊标志
    jsob_tmp.insert("subsequentVisitFlag", "NO");  //复诊标识  YES：复诊 NO：非复诊

    if(!db_m.isOpen())
    {
        ui->textEdit->append("\n");
        ui->textEdit->append("database connection is losed, now connecting ...  ");

        if(!get_db_connect())
        {
            ui->textEdit->append("database connection error.  ");

            jsob_tmp.insert("tip", "数据库连接失败！");
            jsob_tmp.insert("flag", "500");

            jsar_ret << jsob_tmp;

            return jsar_ret;
        }
    }

    QString sq;
    //检索最后一次挂号 clinic_code
    sq = "select clinic_code from fin_opr_register where idenno = '"
            + str_idenno + "' order by reg_date desc";

    qDebug()<<"检索最后一次挂号 clinic_code : "<<sq;


    if(qrm[channel]->exec(sq))
    {
        if(qrm[channel]->next())
        {
            sq = "select zd1, zd2, zd3, diag_date from ys_bz_e_rec where clinic_code = '"
                    + qrm[channel]->value(0).toString() + "'";

            qDebug()<<"检索最后一次挂号关联的诊断 : "<<sq;
            if(qrm[channel]->exec(sq))
            {
                if(qrm[channel]->next())
                {
                    QString diag = qrm[channel]->value(0).toString();
                    if(!qrm[channel]->value(1).toString().isEmpty())
                    {
                        diag.append("|");
                        diag.append(qrm[channel]->value(1).toString());
                    }

                    if(!qrm[channel]->value(2).toString().isEmpty())
                    {
                        diag.append("|");
                        diag.append(qrm[channel]->value(2).toString());
                    }

                    jsob_tmp.insert("subsequentVisitFlag", "YES");  //复诊标识  YES：复诊 NO：非复诊
                    jsob_tmp.insert("consultDiagnosisType", "1");  //首诊诊断类型  1 文字 2 图片 jpg 格式3 图片 png 格式4 图片 bmp 格式
                    jsob_tmp.insert("consultOrg", "沈阳和平仁晟门诊部"); // 首诊机构
                    jsob_tmp.insert("consultDiagnosis", diag); // 首诊诊断
                    jsob_tmp.insert("consultTime", qrm[channel]->value(3)
                                    .toDate().toString("yyyy-MM-dd hh-mm-ss")); // 首诊时间? 最后一次时间?  YYYY-MM-DD HH:mm:ss)

                    //jsob_state.insert("flag", "100");
                    //jsob_state.insert("tip", "成功");
                    jsob_tmp.insert("tip", "成功");
                    jsob_tmp.insert("flag", "100");

                }
                else
                {
                    qDebug()<<"未检索到最后一次挂号的诊断。";
                    //jsob_state.insert("flag", "100");
                    //jsob_state.insert("tip", "有挂号记录，无诊断记录。");
                    jsob_tmp.insert("tip", "有挂号记录，无诊断记录。");
                    jsob_tmp.insert("flag", "300");
                }
            }
            else
            {
                qDebug()<<"检索最后一次挂号诊断 sql 失败 : "<<sq;
                //jsob_state.insert("flag", "100");
                //jsob_state.insert("tip", "检索挂号关联的诊断 sql 失败。");
                jsob_tmp.insert("tip", "检索挂号关联的诊断 sql 失败。");
                jsob_tmp.insert("flag", "300");
            }
        }
        else
        {
            qDebug()<<"未检索到挂号记录。";
            //jsob_state.insert("flag", "100");
            //jsob_state.insert("tip", "无挂号记录。");
            jsob_tmp.insert("tip", "无挂号记录。");
            jsob_tmp.insert("flag", "300");

        }
    }
    else
    {
        qDebug()<<"检索最后一次挂号 sql 失败 : "<<sq;
        //jsob_state.insert("flag", "100");
        //jsob_state.insert("tip", "检索挂号 sql 失败。");
        jsob_tmp.insert("tip", "检索挂号 sql 失败。");
        jsob_tmp.insert("flag", "300");
    }

    qDebug()<<"检索到的诊断记录:";
    qDebug()<<jsob_tmp;

    //jsar_ret << jsob_state;
    jsar_ret << jsob_tmp;

    QJsonDocument j;
    j.setArray( jsar_ret);
    ui->textEdit->append("\n");
    ui->textEdit->append("result value is : ");
    ui->textEdit->append(j.toJson());

    return jsar_ret;
}

void MainWindow::on_pushButton_clicked()
{
    //    QString str = "abcdefg";
    //    str.indexOf("e");
    //    str.indexOf("ab");
    //    ui->textEdit->append("str.indexOf(ab)");
    //    ui->textEdit->append(QString::number(str.indexOf("ab")));

    ui->textEdit->append("0 : "+QString::number(tcpSocket[0]->state()));
    ui->textEdit->append("1 : "+QString::number(tcpSocket[1]->state()));
    ui->textEdit->append("2 : "+QString::number(tcpSocket[2]->state()));
    ui->textEdit->append("3 : "+QString::number(tcpSocket[3]->state()));
    ui->textEdit->append("4 : "+QString::number(tcpSocket[4]->state()));
    ui->textEdit->append("5 : "+QString::number(tcpSocket[5]->state()));
    ui->textEdit->append("6 : "+QString::number(tcpSocket[6]->state()));
    ui->textEdit->append("7 : "+QString::number(tcpSocket[7]->state()));
    ui->textEdit->append("8 : "+QString::number(tcpSocket[8]->state()));
    ui->textEdit->append("9 : "+QString::number(tcpSocket[9]->state()));

}

void MainWindow::on_pb_send_http_clicked()
{

    QString adr = "http://" + ui->leIP->text() + ":" + ui->lePort->text();
    qDebug()<<"remote address : "<<adr;

    QNetworkAccessManager *mng = new QNetworkAccessManager(this);
    QNetworkRequest rqst;
    rqst.setUrl(QUrl(adr));
    rqst.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");

    reply = mng->post(rqst,ui->le_send->text().toUtf8());



connect(reply, &QNetworkReply::finished, this, [=](){

    if(reply->error() == QNetworkReply::NoError)
    {
        QByteArray ret = reply->readAll();
        qDebug()<<"reply read : "<<ret;
        ui->textEdit->append(ret);
    }
    else
    {
        qDebug()<<"reply error : "<<reply->error();
        //ui->textEdit->append(reply->error());
    }

});



/*
    QJsonObject ob;
        QJsonArray oba;
        QJsonDocument doc;

        QNetworkReply* reply = manager.post(request,indoc.toJson());

        QEventLoop eventLoop;

        QObject::connect(reply, SIGNAL(finished()), &eventLoop, SLOT(quit()));
        QTimer::singleShot(15000, &eventLoop, SLOT(quit()));

        eventLoop.exec(); // 进入等待返回

        QVariant statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);

        if(!statusCode.isValid()){
            QMessageBox::warning(NULL,"注意","http 请求状态错误: " + statusCode.toString());
            //ui->lbGif->setVisible(false);
            return ;
        }

        QNetworkReply::NetworkError err = reply->error();

        if(err != QNetworkReply::NoError){
            QMessageBox::warning(NULL,"注意",reply->errorString());
            //ui->lbGif->setVisible(false);
            return ;
        }

        QByteArray bt = reply->readAll();
        QString t = QString::fromLocal8Bit(bt);

        QJsonParseError json_error;
        QJsonDocument jsdc = QJsonDocument::fromJson(t.toUtf8(), &json_error);
        if(json_error.error != 0 ){
            QMessageBox::warning(NULL,"注意","返回信息解析错误 " + json_error.errorString());
            //ui->lbGif->setVisible(false);
            return ;
        }    //request.setUrl(QUrl(adr));
    request.setUrl(adr);
    request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");


    //QJsonObject inpu;
    QJsonParseError json_error;
    QJsonDocument jsdc = QJsonDocument::fromJson(ui->le_send->text().toUtf8().data(), &json_error);
    if(json_error.error != 0 )
    {
        QMessageBox::information(this, "Note", "入参Json解析错误 " + json_error.errorString());
        return ;
    }

    QString info;
    QJsonObject retValue;

    qDebug()<<"jsdc : "<<jsdc;

    //QNetworkReply* reply = manager.post(request, jsdc.toJson());
    QNetworkReply * reply;

    QEventLoop eventLoop;

    QObject::connect(reply, SIGNAL(finished()), &eventLoop, SLOT(quit()));

    QTimer::singleShot(5000, &eventLoop, SLOT(quit()));

//    reply = manager.post(request, ui->le_send->text().toUtf8());
        reply = manager.get(request, ui->le_send->text().toUtf8());

    eventLoop.exec(); // 进入等待返回

    QVariant statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);

    if(!statusCode.isValid())
    {
        info = "http 请求状态错误: " + statusCode.toString();
        qDebug()<<info;
ui->textEdit->append(info);
         return ;
    }

    QNetworkReply::NetworkError err = reply->error();

    if(err != QNetworkReply::NoError)
    {
        info = "NetworkReply 返回状态错误：" + reply->errorString();
        qDebug()<<"返回状态错误："<<info;
ui->textEdit->append(info);
        return ;
    }

    // 获取MIME类型和字符集
    QString contentType = reply->header(QNetworkRequest::ContentTypeHeader).toString();
    QString charset = contentType.split("charset=").last();
    QString encoding = charset.isEmpty() ? "UTF-8" : charset; // 默认使用UTF-8编码

    QByteArray bt = reply->readAll();

    qDebug()<<"return value : "<< QString(bt);

    ui->textEdit->append("\n");
    ui->textEdit->append(QString(bt));
    */
}
